package com.wlit.server;

import com.wlit.IExtOps;
import com.wlit.handler.NettyWebSocketHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.apache.log4j.Logger;

import java.io.InputStream;
import java.util.Properties;

public class NettyWebServer {

    private Logger logger = Logger.getLogger(NettyWebServer.class);

    private EventLoopGroup boss = new NioEventLoopGroup();
    private EventLoopGroup worker = new NioEventLoopGroup();

    private IExtOps extOps;

    public NettyWebServer(IExtOps ops){
        this.extOps = ops;
    }


    public void run() {
        int serverPort = 7011;
        try {
            Properties properties = new Properties();
            InputStream in = NettyWebServer.class.getResourceAsStream("/config.properties");
            properties.load(in);
            serverPort = Integer.valueOf(properties.getProperty("server.port"));
            in.close();
        }catch (Exception ex){
            ex.printStackTrace();
        }

        try {
            //辅助启动工具类
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //HttpRequestDecoder和HttpResponseEncoder的一个组合，针对http协议进行编解码
                            pipeline.addLast(new HttpServerCodec());
                            //分块向客户端写数据，防止发送大文件时导致内存溢出
                            pipeline.addLast(new ChunkedWriteHandler());
                            //将HttpMessage和HttpContents聚合到一个完成的 FullHttpRequest或FullHttpResponse中
                            pipeline.addLast(new HttpObjectAggregator(1024 * 1024));
                            //协议处理器
                            pipeline.addLast(new WebSocketServerProtocolHandler("/RFIDScanner"));
                            //自定义的处理器
                            pipeline.addLast(new NettyWebSocketHandler(extOps));
                        }
                    });
            //绑定端口，同步启动
            ChannelFuture future = bootstrap.bind(serverPort).sync();
            logger.info("WebSocket启动成功:"+serverPort);
            System.out.println("WebSocket启动成功:"+serverPort);
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            logger.info("WebSocket启动失败:"+e.getMessage());
            System.out.println("WebSocket启动失败:"+e.getMessage());
            e.printStackTrace();
            System.exit(0);
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    public void close(){
        System.out.println("关闭WebSocket服务器");
        boss.shutdownGracefully();
        worker.shutdownGracefully();
    }


}
